#include "QsUdpReceiver.h"
#include "QsUdpGlobal.h"
#include <QThread>
#include <QHostAddress>
#include <QDebug>

QsUdpReceiver::QsUdpReceiver(QObject* parent)
    : QObject(parent)
    , m_info(QHOSTADDRESS_ANY_COMPAT, 45454)
{
}

QsUdpReceiver::QsUdpReceiver(const QsUdpInfo& info, QObject* parent)
    : QObject(parent)
    , m_info(info)
{
}

QsUdpReceiver::~QsUdpReceiver()
{
    cleanup();
}

void QsUdpReceiver::init(const QsUdpInfo& info)
{
    // 更新UDP信息
    m_info = info;
    
    if (m_socket) {
        m_socket->deleteLater();
    }
    m_socket = new QUdpSocket(this);
    connect(m_socket, &QUdpSocket::stateChanged, this, &QsUdpReceiver::stateChanged);
    connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QUdpSocket::errorOccurred),
            this, [this](QAbstractSocket::SocketError){ emit errorOccurred(m_socket->errorString()); });
    m_socket->bind(m_info.address, m_info.port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
    connect(m_socket, &QUdpSocket::readyRead, this, &QsUdpReceiver::onReadyRead);
}

void QsUdpReceiver::cleanup()
{
    if (m_socket) {
        m_socket->close();
        m_socket->deleteLater();
        m_socket = nullptr;
    }
}

void QsUdpReceiver::onReadyRead()
{
    while (m_socket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(int(m_socket->pendingDatagramSize()));
        QHostAddress senderAddr;
        quint16 senderPort;
        m_socket->readDatagram(datagram.data(), datagram.size(), &senderAddr, &senderPort);
        
        // 先判断长度是否足够包含头部
        if (datagram.size() < int(sizeof(QsUdpPacketHeader))) {
            continue;
        }
        
        QsUdpPacketHeader header;
        memcpy(&header, datagram.constData(), sizeof(QsUdpPacketHeader));
        
        // 验证魔数
        if (memcmp(header.magic, "QUDP", 4) != 0) {
            continue;
        }
        
        // 验证数据长度
        if (datagram.size() != int(sizeof(QsUdpPacketHeader) + header.length)) {
            continue;
        }
        
        QByteArray data = datagram.mid(sizeof(QsUdpPacketHeader));
        emit received(header, data, QsUdpInfo(senderAddr, senderPort));
    }
}

void QsUdpReceiver::setSocketOption(QAbstractSocket::SocketOption option, const QVariant& value)
{
    if (m_socket) {
        m_socket->setSocketOption(option, value);
    }
}

bool QsUdpReceiver::joinMulticastGroup(const QHostAddress& groupAddress, const QNetworkInterface& iface)
{
    if (m_socket) {
        bool ok = m_socket->joinMulticastGroup(groupAddress, iface);
        if (ok) {
            emit multicastJoined(groupAddress);
        }
        return ok;
    }
    return false;
}

bool QsUdpReceiver::leaveMulticastGroup(const QHostAddress& groupAddress, const QNetworkInterface& iface)
{
    if (m_socket) {
        return m_socket->leaveMulticastGroup(groupAddress, iface);
    }
    return false;
}

void QsUdpReceiver::enableBroadcast(bool enabled)
{
    if (m_socket) {
        m_socket->setSocketOption(QAbstractSocket::BroadcastTtlOption, enabled ? 1 : 0);
        emit broadcastEnabled(enabled);
    }
} 